﻿using System;
using System.Collections.Generic;
using System.Linq;
using Epitech.Krisk.Kinect.Sensor;
using Epitech.Krisk.Xna.ScreenManagerLib.ScreenManager;
using Epitech.Krisk.Xna.UI.Game.Utils;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Epitech.Krisk.Xna.UI.Game.Menu;
using Microsoft.Xna.Framework.Input;

namespace Epitech.Krisk.Xna.UI.Game.InGame.Gameplay
{
    public enum GamePlayType
    {
        Classic,
        Domination,
        None
    }

    public class GamePlay : AGameObject
    {
        private GamePlayType _gameType;
        public List<TerritoryCard> Cards { get; set; }

        private TimeSpan _gameStart = TimeSpan.Zero;
        public Turn GameTurn { get; set; }
        private readonly Random _rand;
        private Territory _select;
        private Territory _nextSelect;

        private readonly List<AGameObject> _listObject = new List<AGameObject>();

        private Dictionary<Territory, Army> _terrSelect;

        public ScreenManager ScreenManager { get; set; }

        private PanelRenfort _panel;
        private Territory _lastselect = null;
        private SelectPanel _selectpanel;

        public GamePlayType GameType
        {
            get { return _gameType; }
            set { _gameType = value; }
        }

        private readonly List<Color> _colors = new List<Color> { Color.SteelBlue, Color.Tomato, Color.ForestGreen, Color.MediumVioletRed, Color.Goldenrod };

        private List<FightInfo> _endfight;
        private bool _nocheat = true;
        private List<Keys> _lastPressedKeys = new List<Keys>();
        private List<Keys> _konamicode = new List<Keys> { Keys.Up, Keys.Up, Keys.Down, Keys.Down, Keys.Left, Keys.Right, Keys.Left, Keys.Right, Keys.B, Keys.A };
        private bool _fromCharge = false;
        public List<Player> Players { get; set; }

        public GamePlay(int nbplayer, GamePlayType gt)
        {
            _gameType = gt;
            Players = new List<Player>();
            for (int i = 0; i < nbplayer; i++)
            {
                Players.Add(new Player());
                Players.Last().Name = String.Format("Joueur {0}", i + 1);
                Players.Last().State = PlayerState.Alive;
                Players.Last().Color = _colors[i];
            }
            GameTurn = new Turn {Player = Players[0], State = TurnState.Begin};
            _rand = new Random();
            SensorManager.Instance.StartSensorAction(SensorManager.StartAction.Swipe);
            SensorManager.Instance.StartSensorAction(SensorManager.StartAction.Zoom);
            SensorManager.Instance.StartSensorAction(SensorManager.StartAction.Cursor);
            RiskAction.Rand = _rand;
        }

        public GamePlay(GamePlayType gt)
        {
            _gameType = gt;
            _rand = new Random();
            SensorManager.Instance.StartSensorAction(SensorManager.StartAction.Swipe);
            SensorManager.Instance.StartSensorAction(SensorManager.StartAction.Zoom);
            SensorManager.Instance.StartSensorAction(SensorManager.StartAction.Cursor);
            _fromCharge = true;
        }

        public override void LoadContent()
        {
            TerritoryCard.MakeCards(Content);
            Continent.CreateContinentAndTerritory();
            QuestCard.Init(Content);
            Territory.RecupListTerritory();
            Cards = TerritoryCard.TerritoryCards;
            _endfight = new List<FightInfo>();

            foreach (Territory territory in Territory.Territories)
            {
                territory.Clicked += TerritorySelectionned;
            }

            if (!_fromCharge)
            {
                while (Territory.Territories.Count > 0)
                {
                    foreach (Player player in Players)
                    {
                        if (Territory.Territories.Count > 0)
                        {
                            Territory terr = Territory.Territories[_rand.Next(Territory.Territories.Count)];
                            Territory.Territories.Remove(terr);
                            terr.Owner = player;
                            terr.SpriteBatch = SpriteBatch;
                            terr.Content = Content;
                            terr.ViewPort = ViewPort;
                            var tmp = new Army {WarPlane = 0, Tank = 0, Soldier = 2};
                            player.OwnTerritory.Add(terr, tmp);
                        }
                    }
                }

                if (_gameType == GamePlayType.Classic)
                {
                    foreach (var player in Players)
                    {
                        int nb = _rand.Next(QuestCard.QuestCards.Count);
                        player.QuestCard = QuestCard.QuestCards[nb];
                        QuestCard.QuestCards.RemoveAt(nb);
                    }
                }
                NewRenfort();
            }
        }

        private void TerritorySelectionned(object sender, EventArgs e)
        {
            var terr = sender as Territory;

            if (terr != null)
                _select = terr;                
        }

        private void NewRenfort()
        {
            #region Renfort de debut de tour

            int total = GameTurn.Player.OwnTerritory.Sum(keyValuePair => keyValuePair.Value.TotalSoldier());
            GameTurn.Player.ReinforcementArmy += new Army(total / 3);
            bool ok = true;
            foreach (var territory in Continent.Continents["Afrique"].Territories)
            {
                if (territory.Owner != GameTurn.Player)
                    ok = false;
            }
            if (ok)
                GameTurn.Player.ReinforcementArmy += new Army(3);
            ok = true;
            foreach (var territory in Continent.Continents["Asie"].Territories)
            {
                if (territory.Owner != GameTurn.Player)
                    ok = false;
            }
            if (ok)
                GameTurn.Player.ReinforcementArmy += new Army(7);
            ok = true;
            foreach (var territory in Continent.Continents["Europe"].Territories)
            {
                if (territory.Owner != GameTurn.Player)
                    ok = false;
            }
            if (ok)
                GameTurn.Player.ReinforcementArmy += new Army(5);
            ok = true;
            foreach (var territory in Continent.Continents["Amerique du Nord"].Territories)
            {
                if (territory.Owner != GameTurn.Player)
                    ok = false;
            }
            if (ok)
                GameTurn.Player.ReinforcementArmy += new Army(5);
            ok = true;
            foreach (var territory in Continent.Continents["Amerique du Sud"].Territories)
            {
                if (territory.Owner != GameTurn.Player)
                    ok = false;
            }
            if (ok)
                GameTurn.Player.ReinforcementArmy += new Army(2);
            ok = true;
            foreach (var territory in Continent.Continents["Oceanie"].Territories)
            {
                if (territory.Owner != GameTurn.Player)
                    ok = false;
            }
            if (ok)
                GameTurn.Player.ReinforcementArmy += new Army(2);

            #endregion
        }

        public void NextTurn()
        {

            #region Reset

            if (_terrSelect != null)
            {
                foreach (var army in _terrSelect)
                {
                    army.Key.IsSelected = false;
                }
            }
            _terrSelect = null;
            if (_panel != null)
            {
                _panel.End = true;
                _lastselect = null;
                _select = null;
            }
            if (_selectpanel != null)
            {
                _selectpanel.End = true;
                _lastselect = null;
                _select = null;
            }

            #endregion
            
            if (GameTurn.Next())
            {
                do
                {
                    GameTurn.Player = Players.IndexOf(GameTurn.Player) != Players.Count - 1
                                          ? Players[Players.IndexOf(GameTurn.Player) + 1]
                                          : Players[0];
                } while (GameTurn.Player.State != PlayerState.Dead);
            }
            if (GameTurn.State == TurnState.Begin)
            {
                NewRenfort();
            }
        }

        public override void HandleInput(InputState input)
        {
            PlayerIndex tmp;

            foreach (AGameObject obj in _listObject)
            {
                obj.HandleInput(input);
            }

            foreach (var fightInfo in _endfight)
            {
                fightInfo.HandleInput(input);
            }

            _lastPressedKeys.AddRange(input.GetPressedKeys().ToList());
            if (input.IsNewButtonPress(Buttons.Y, null, out tmp))
            {
                NextTurn();
            }
        }

        public override void Draw(GameTime gameTime)
        {
            base.Draw(gameTime);
           
            //Vector2 pos = Vector2.Zero;
            //if (_terrSelect != null)
            //{
            //    SpriteBatch.Begin();
            //    foreach (KeyValuePair<Territory, Army> territory in _terrSelect)
            //    {
            //        SpriteBatch.DrawString(ScreenManager.Font, territory.Key.Name, pos, Color.Black, 0f, Vector2.One, 0.5f,
            //                               SpriteEffects.None, 0f);
            //        pos.Y += ScreenManager.Font.MeasureString(territory.Key.Name).Y*0.5f;
            //    }
            //    SpriteBatch.End();
            //}

            foreach (var aGameObject in _listObject)
            {
                aGameObject.Draw(gameTime);
            }

            foreach (var fightInfo in _endfight)
            {
                fightInfo.Draw(gameTime);
            }
            
        }

        public override void Update(GameTime gameTime, bool otherScreenHasFocus, bool coveredByOtherScreen)
        {
            if (_lastPressedKeys.Count > 10)
            {
                int nb = _lastPressedKeys.Count - 10;
                _lastPressedKeys.RemoveRange(0, nb);
            }

            #region CheatCode :p

            if (_lastPressedKeys.Count == 10 && _nocheat)
            {

                _nocheat = false;

                for (int i = 0; i < _lastPressedKeys.Count; i++)
                {
                    if (_lastPressedKeys[i] != _konamicode[i])
                        _nocheat = true;
                }
            }

            #endregion

            if (_gameStart == TimeSpan.Zero)
                _gameStart = gameTime.TotalGameTime;

            // Check end game
            int alivepl = 0;
            if (GameType == GamePlayType.Classic)
            {
                if (GameTurn.Player.QuestCard.IsValidate(GameTurn.Player))
                {
                    GameTurn.Player.Win = true;
                    ScreenManager.RemoveLastScreen();
                    ScreenManager.AddScreen(new EndGameView(this), null);
                }
            }
            else
            {
                if (Players != null)
                    alivepl = Players.Count(player => player.State != PlayerState.Dead);
                if (alivepl == 1)
                {
                    ScreenManager.RemoveLastScreen();
                    ScreenManager.AddScreen(new EndGameView(this), null);
                }
            }

            foreach (var player in Players)
            {
                player.Update(gameTime, _gameStart);
            }

            #region RickAction
            
            if (_select != null)
            {
                switch (GameTurn.State)
                {
                    case TurnState.Begin:

                        #region Renfort

                        if (_select.Owner == GameTurn.Player && _select != _lastselect)
                        {
                            if (_panel == null)
                            {
                                _panel = new PanelRenfort(_select, GameTurn.Player) { Content = Content, SpriteBatch = SpriteBatch, ViewPort = ViewPort };
                                _panel.LoadContent();
                                _listObject.Add(_panel);
                                _lastselect = _select;
                            }
                            else
                            {
                                _nextSelect = _select;
                                _panel.End = true;
                                _select = null;
                            }
                        }

                        #endregion
                        
                        break;
                    case TurnState.Fight:

                        #region Fight
                        if (_select.IsSelected)
                        {
                            _select.IsSelected = false;
                            _terrSelect.Remove(_select);
                            _select = null;
                            break;
                        }
                        if (_select.Owner == GameTurn.Player && _select != _lastselect)
                        {
                            if (_selectpanel == null)
                            {
                                _selectpanel = new SelectPanel(_select, GameTurn.Player) { Content = Content, SpriteBatch = SpriteBatch, ViewPort = ViewPort };
                                _selectpanel.LoadContent();
                                _listObject.Add(_selectpanel);
                                _lastselect = _select;
                            }
                            else
                            {
                                _nextSelect = _select;
                                _selectpanel.End = true;
                                _select = null;
                            }
                        }
                        else if (_select.Owner != GameTurn.Player && _terrSelect != null && _terrSelect.Count >= 1)
                        {
                            bool ok = true;
                            foreach (var army in _terrSelect)
                            {
                                bool ok1 = false;
                                foreach (var territory in _select.Neighbors)
                                {
                                    if (territory.Name.ToLower() == army.Key.Name.ToLower())
                                        ok1 = true;
                                }
                                if (!ok1)
                                    ok = false;
                            }
                            if (ok)
                            {
                                Army atkb = new Army();
                                foreach (var army in _terrSelect)
                                {
                                    atkb += army.Value;
                                }
                                Army atk;
                                Army defb = new Army(_select.Owner.OwnTerritory[_select].TotalSoldier());
                                Army def;
                                bool fight = RiskAction.Fight(_terrSelect.ToList(), _select, out atk, out def);
                                if (fight && GameTurn.Player.Cards.Count < 5)
                                {
                                    TerritoryCard card = Cards[_rand.Next(Cards.Count)];
                                    Cards.Remove(card);
                                    GameTurn.Player.Cards.Add(card);
                                }

                                _endfight.Add(new FightInfo(fight, atkb - atk, defb - def)
                                                {SpriteBatch = SpriteBatch, ViewPort = ViewPort, Content = Content});
                                _endfight.Last().LoadContent();
                            }
                            else
                            {
                                ScreenManager.AddScreen(new InfoMessage("Veuillez selectionner\ndes territoires voisins"), null);
                            }
                            if (_terrSelect != null)
                            {
                                foreach (var army in _terrSelect)
                                {
                                    army.Key.IsSelected = false;
                                }
                            }
                            _terrSelect = null;
                            _select = null;
                        } 

	                    #endregion

                        break;
                    case TurnState.Move:

                        #region Move

                        if (_select.Owner == GameTurn.Player && _select != _lastselect && (_terrSelect == null || _terrSelect.Count == 0))
                        {
                            if (_selectpanel == null)
                            {
                                _selectpanel = new SelectPanel(_select, GameTurn.Player) { Content = Content, SpriteBatch = SpriteBatch, ViewPort = ViewPort };
                                _selectpanel.LoadContent();
                                _listObject.Add(_selectpanel);
                                _lastselect = _select;
                            }
                            else
                            {
                                _nextSelect = _select;
                                _selectpanel.End = true;
                                _select = null;
                            }
                        }
                        else if (_select.Owner == GameTurn.Player && _terrSelect != null && _terrSelect.Count >= 1)
                        {
                            bool ok = true;
                            foreach (var army in _terrSelect)
                            {
                                if (!_select.Neighbors.Contains(army.Key))
                                    ok = false;
                            }
                            if (ok)
                            {
                                RiskAction.Move(_terrSelect.ToList(), _select);
                                if (_terrSelect != null)
                                {
                                    foreach (var army in _terrSelect)
                                    {
                                        army.Key.IsSelected = false;
                                    }
                                }
                                _terrSelect = null;
                                _select = null;
                            }
                            else
                            {
                                ScreenManager.AddScreen(new InfoMessage("Veuillez selectionner\ndes territoires voisins"), null);
                            }
                        }

                        #endregion
                       
                        break;
                }
            }

            #endregion

            #region EndFight

            for (int i = 0; i < _endfight.Count; i++)
            {
                if (_endfight[i].ToDelete)
                {
                    _endfight.RemoveAt(i);
                    --i;
                }
            }

            #endregion

            #region PanelRenfort
            
            if (_panel != null && _panel.ToDelete)
            {
                _listObject.Remove(_panel);
                _select = null;
                _panel = null;
                if (_nextSelect != null)
                    _select = _nextSelect;
                _nextSelect = null;
            }

            if (_panel != null && _panel.State != PanelState.None)
            {
                if (_panel.State == PanelState.Ok && !_panel.End)
                {
                    if (_select != null)
                    {
                        _select.Owner.OwnTerritory[_select] += _panel.Renfort;
                        _select.Owner.ReinforcementArmy -= new Army(_panel.Renfort.TotalSoldier());
                    }
                }
                if (_panel != null) _panel.End = true;
                _select = null;
                _lastselect = null;
            }

            #endregion

            #region PanelCombat

            if (_selectpanel != null && _selectpanel.ToDelete)
            {
                _listObject.Remove(_selectpanel);
                _select = null;
                _selectpanel = null;
                if (_nextSelect != null)
                    _select = _nextSelect;
                _nextSelect = null;
            }

            // Combat
            if (_selectpanel != null && _selectpanel.State != PanelState.None)
            {
                if (_selectpanel.State == PanelState.Ok && !_selectpanel.End)
                {
                    bool ok = false;
                    if (_terrSelect != null)
                    {
                        foreach (var terr in _terrSelect)
                        {
                            if (terr.Key == _select)
                                ok = true;
                        }
                    }
                    if (_terrSelect == null)
                        _terrSelect = new Dictionary<Territory, Army>();
                    if (ok)
                        _terrSelect.Remove(_select);
                    else if (_select.Owner == GameTurn.Player && _selectpanel.Renfort > 0)
                    {
                        if (_nocheat)
                        {
                            foreach (var army in _terrSelect)
                            {
                                army.Key.IsSelected = false;
                            }
                            _terrSelect.Clear();
                        }
                        _terrSelect.Add(_select, _selectpanel.Renfort);
                        _select.IsSelected = true;
                    }
                    _select = null;
                }
                if (_selectpanel != null) _selectpanel.End = true;
                _select = null;
                _lastselect = null;
            }

            #endregion

            #region ObjectsUpdate

            foreach (var aGameObject in _listObject)
            {
                aGameObject.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
            }

            foreach (var fightInfo in _endfight)
            {
                fightInfo.Update(gameTime, otherScreenHasFocus, coveredByOtherScreen);
            }

            #endregion
        }

        internal bool EchangeCard(List<ClickableCard> selected)
        {
            if (selected.Count == 3)
            {
                var suit = new SuitCard(selected);

                if (suit.IsValid)
                {
                    GameTurn.Player.ReinforcementArmy += new Army(suit.ArmyWon);
                    foreach (var clickableCard in selected)
                    {
                        RemoveCard(clickableCard);
                    }
                    return true;
                }
                ScreenManager.AddScreen(new InfoMessage("Combinaison\nde carte invalide"), null);
                return false;
            }
            ScreenManager.AddScreen(new InfoMessage("Nombre de carte\nselectionnee incorrect"), null);
            return false;
        }

        internal void RemoveCard(ClickableCard clickableCard)
        {
            GameTurn.Player.Cards.Remove(clickableCard.TerritoryCard);
            Cards.Add(clickableCard.TerritoryCard);
        }
    }
}
